package com.learn.security.theory.message_digest;

import com.learn.security.utils.message_digest.MDUtil;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.MessageDigest;
import java.security.Security;

/**
 * MD算法
 * <p>
 * 特点：单项加密
 * 128位摘要信息
 * <p>
 * 类别：          摘要长度          实现方法（jdk基本实现，bc补充，cc简化）
 * MD2         128                 jdk
 * MD4         128                 bc
 * MD5         128                 jdk
 */
public class MDTest {

    private static final String encodeStr = "MD5 test";

    public static void main(String[] args) {
        MDUtil();

        jdkMD5();

        jdkMD2();

        bcMD5();

        bcMD4();

        bc2jdkMD4();

        ccMD5();

        ccMD2();
    }

    // 用MDUtil实现：MD5
    private static void MDUtil() {
        byte[] md5Bytes = MDUtil.encryptMD5(encodeStr.getBytes());
        System.out.println("MDUtil MD5:" + Hex.encodeHexString(md5Bytes));
    }

    // 用jdk实现:MD5
    private static void jdkMD5() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] md5Bytes = md.digest(encodeStr.getBytes());
            System.out.println("JDK MD5:" + Hex.encodeHexString(md5Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 用jdk实现:MD2
    private static void jdkMD2() {
        try {
            MessageDigest md = MessageDigest.getInstance("MD2");
            byte[] md2Bytes = md.digest(encodeStr.getBytes());
            System.out.println("JDK MD2:" + Hex.encodeHexString(md2Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 用bouncy castle实现:MD5
    private static void bcMD5() {
        MD5Digest digest = new MD5Digest();
        digest.update(encodeStr.getBytes(), 0, encodeStr.getBytes().length);
        byte[] md5Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md5Bytes, 0);
        System.out.println("bouncy castle MD5:" + org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes));
    }

    // 用bouncy castle实现:MD4
    private static void bcMD4() {
        MD4Digest digest = new MD4Digest();
        digest.update(encodeStr.getBytes(), 0, encodeStr.getBytes().length);
        byte[] md4Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md4Bytes, 0);
        System.out.println("bouncy castle MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes));
    }

    // 用bouncy castle与jdk结合实现:MD4
    private static void bc2jdkMD4() {
        try {
            Security.addProvider(new BouncyCastleProvider());
            MessageDigest md = MessageDigest.getInstance("MD4");
            byte[] md4Bytes = md.digest(encodeStr.getBytes());
            System.out.println("bc and JDK MD4:" + Hex.encodeHexString(md4Bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 用common codes实现实现:MD5
    private static void ccMD5() {
        System.out.println("common codes MD5:" + DigestUtils.md5Hex(encodeStr.getBytes()));
    }

    // 用common codes实现实现:MD2
    private static void ccMD2() {
        System.out.println("common codes MD2:" + DigestUtils.md2Hex(encodeStr.getBytes()));
    }
}
